package com.durian.ui.dialog

import android.content.DialogInterface
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding
import com.durian.base.R
import com.durian.base.frame.activity.ActivityFrame
import com.durian.base.frame.fragment.FragmentFrame
import java.util.concurrent.ConcurrentHashMap

open class NiceDialogFragment<VB : ViewBinding> : FixDialogFragment() {
    private companion object{
        const val CONFIG_TAG = "_CONFIG"
        val TagManager = ConcurrentHashMap<String,String>()
    }
    private var convertListener: ((VB, NiceDialogFragment<VB>) -> Unit)? = null
    private var onDismissListener: DialogInterface.OnDismissListener? = null
    private var config : NiceDialogConfig? = NiceDialogConfig()
    private var vb : VB? = null
    private var vbClazz : Class<VB>? = null
    private var fragmentTag = System.currentTimeMillis().toString()

    init {
        setStyle(STYLE_NO_TITLE, R.style.base_ui_nice_dialog)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //恢复保存的数据
        if (savedInstanceState?.containsKey(CONFIG_TAG) == true) {
            config = savedInstanceState.getParcelable(CONFIG_TAG)
        }
    }

    override fun onStart() {
        super.onStart()
        initParams()
    }

    fun layout(clazz: Class<VB>) : NiceDialogFragment<VB>{
        vbClazz = clazz
        fragmentTag = clazz.name
        return this
    }

    fun config(func : (NiceDialogConfig)->Unit): NiceDialogFragment<VB>{
        config?.let { func(it) }
        return this
    }

    fun bind(block: ((VB, NiceDialogFragment<VB>) -> Unit)? = null): NiceDialogFragment<VB>{
        this.convertListener = block
        return this
    }

    fun dismissListener(block: ((NiceDialogFragment<VB>) -> Unit)? = null): NiceDialogFragment<VB>{
        this.onDismissListener = DialogInterface.OnDismissListener {
            block?.invoke(this)
        }
        return this
    }

    fun show(fragment: FragmentFrame) : NiceDialogFragment<VB>{
        show(fragment.childFragmentManager)
        return this
    }

    fun show(activity: ActivityFrame) : NiceDialogFragment<VB> {
        show(activity.supportFragmentManager)
        return this
    }

    fun show(manager: FragmentManager) : NiceDialogFragment<VB> {
        val dialogTag = fragmentTag
        if (dialogTag.isNotEmpty() && TagManager.containsKey(dialogTag)){
            return this
        }
        showDialog(manager,dialogTag){
            TagManager[dialogTag] = dialogTag
        }
        return this
    }

    private fun showDialog(manager: FragmentManager,tag : String,success : ()->Unit){
        kotlin.runCatching {
            manager.beginTransaction().let { transaction->
                if (tag.isNotEmpty()){
                    manager.findFragmentByTag(tag)?.let { transaction.remove(it) }
                }
                transaction.add(this,tag).commitAllowingStateLoss()
                success.invoke()
            }
        }
    }

    override fun onCancel(dialog: DialogInterface) {
        super.onCancel(dialog)
        removeTag()
    }

    private fun removeTag(){
        if (TagManager.containsKey(fragmentTag)){
            TagManager.remove(fragmentTag)
        }
        onDismissListener = null
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        onDismissListener?.onDismiss(dialog)
        removeTag()
    }

    private fun initParams() {
        val window = dialog!!.window
        val niceConfig = config
        if (window != null && niceConfig != null) {
            //设置dialog进入、退出的动画
            window.setWindowAnimations(niceConfig.animStyleRes)
            val lp = window.attributes
            //调节灰色背景透明度[0-1]，默认0.5f
            lp.dimAmount = niceConfig.dimAmount
            //是否在底部显示
            if (niceConfig.showBottom) {
                lp.gravity = Gravity.BOTTOM
            }
            //设置dialog宽度
            lp.width = niceConfig.width
            //设置dialog高度
            lp.height = niceConfig.height
            window.attributes = lp
            isCancelable = niceConfig.outCancel
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        try {
            vb = reflectBinding(inflater,container)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return vb?.root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        vb?.let {
            convertListener?.invoke(it,this)
        }
    }

    /**
     * 反射实例化binding
     */
    private fun reflectBinding(inflater: LayoutInflater, container: ViewGroup?): VB {
        val inflateMethod = vbClazz?.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java,Boolean::class.java)
        return inflateMethod?.invoke(null,inflater,container,false) as VB
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putParcelable(CONFIG_TAG,config)
    }

}